﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath;
using System.Collections;
using POMotionScheduler;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;

namespace POMotionScheduler
{
    public partial class Main : Form
    {
        private static bool _DEBUG_ = false;
        public Main()
        {
            InitializeComponent();
        }

        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll")]
        public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll")]
        public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        private string _fileConfigName;
        private string _executeString = "";
        private ArrayList _executeList = new ArrayList();
        private ArrayList _sceneTime = new ArrayList();

        string SCHEDULE_TYPE = "";
        string NAME = "";
        string EVENT_ID = "";
        string ITEM_ID = "";
        DateTime START_TIME;
        int INTERVAL = 0;
        string PLAY_TYPE = "";

        public string FileConfig
        {
            get { return _fileConfigName; }
        }

        private void menuExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
            this.ShowInTaskbar = false;
        }

        private void menuShow_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Normal;
            this.ShowInTaskbar = true;
        }

        private void loadConfigurationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadConfig();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            LoadConfig();
        }

        private void LoadConfig()
        {
            OpenFileDialog file = new OpenFileDialog();
            file.Filter = "Configuration file (*.xml)|*.xml";
            file.Multiselect = false;
            file.ShowDialog();
            _fileConfigName = file.FileName;
            ReadConfig();
        }

        private void ReadConfig()
        {
            try
            {

                XMLValidator xmlConfig = new XMLValidator(FileConfig);
                if (xmlConfig.Validate())
                {

                    XmlDocument xDoc = new XmlDocument();
                    xDoc.Load(FileConfig);

                    XPathNavigator nav = xDoc.CreateNavigator();
                    XPathNodeIterator nodes;

                    nodes = nav.Select("/Document/Data/Section[@Name='Scheduler']/Items[@Name='Schedule']/Item");
                    foreach (XPathNavigator item in nodes)
                    {
                        SCHEDULE_TYPE = item.GetAttribute("C00", "");
                        NAME = item.GetAttribute("C01", "");
                        EVENT_ID = item.GetAttribute("C02", "");
                        ITEM_ID = item.GetAttribute("C03", "");
                        if (item.GetAttribute("C04", "") != "")
                        {
                            START_TIME = Convert.ToDateTime(item.GetAttribute("C04", ""));
                        }
                        else
                        {
                            START_TIME = DateTime.Now;
                        }
                        INTERVAL = Convert.ToInt32(item.GetAttribute("C05", ""));
                        PLAY_TYPE = item.GetAttribute("C06", "");

                        if ((SCHEDULE_TYPE != "") && (SCHEDULE_TYPE == "3"))
                        {
                            SequenceSchedule();
                        }
                    }
                }
                else
                {
                    ArrayList err = xmlConfig.GetErrors();
                    string xmlError = "";
                    foreach (string er in err)
                    {
                        xmlError += er + Environment.NewLine;
                    }
                    MessageBox.Show(xmlError);
                }
            }
            catch (Exception Ex)
            {
                if (_DEBUG_) Console.WriteLine(Ex);
                MessageBox.Show(Ex.Message,"Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
            }
        }

        private void SequenceSchedule()
        {
            try
            {
                _executeList.Clear();
                XmlDocument xDoc = new XmlDocument();
                xDoc.Load(FileConfig);

                XPathNavigator nav = xDoc.CreateNavigator();
                XPathNodeIterator nodes;

                nodes = nav.Select("/Document/Data/Section[@Name='Event']/Items[@Name='SceneConfig']/Item");
                foreach (XPathNavigator item in nodes)
                {
                    string programPath = item.GetAttribute("C00", "");
                    string scenePath = item.GetAttribute("C01", "");
                    _executeString = programPath + "#" + scenePath;
                }

                //scene name
                nodes = nav.Select("/Document/Data/Section[@Name='Event']/Items[@Name='SceneSeq']/Item");
                foreach (XPathNavigator item in nodes)
                {
                    string sceneName = item.GetAttribute("Name", "");
                    string sceneTime = item.GetAttribute("WAIT", "");
                    string fullPath = _executeString + sceneName;
                    _executeList.Add(fullPath);
                    _sceneTime.Add(sceneTime);
                }
                //if read successful then create schedule.
                CreateSchedule();
            }
            catch (POMotionScheduler.SchedulerException ex)
            {
                DialogResult result = MessageBox.Show(ex.Message+".\nDo you want to add new schedule?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button3);
                if (result == System.Windows.Forms.DialogResult.Yes)
                {
                    Schedule s = Scheduler.GetSchedule(NAME);
                    Scheduler.RemoveSchedule(s);
                    CreateSchedule();
                }
            }
            catch (Exception Ex)
            {
                Console.WriteLine(Ex);
                if(_DEBUG_) MessageBox.Show(Ex.Message);
            }
        }

        private void CreateSchedule()
        {
            Schedule s;
            // create and add different types of schedules
            s = new IntervalSchedule(NAME, DateTime.Now, INTERVAL, TimeSpan.Zero, new TimeSpan(TimeSpan.TicksPerDay));
            s.OnTrigger += new POMotionScheduler.Invoke(s_OnTriggerSEQ);
            Scheduler.AddSchedule(s);
        }

        private void CreateOneTimeSchedule()
        {
            Schedule s;
            s = new OneTimeSchedule(NAME, DateTime.Now.AddSeconds(0));
        }

        Process proc = new Process();
        bool pomoRunning = false;
        private void ExecuteProcWithParam(string fileName, string Param)
        {
            //PO-MOtion-IR
            pomoRunning = false;
            Process[] processes = Process.GetProcesses();

            foreach (Process process in processes)
            {
                if (process.ProcessName == "PO-MOtion-IR")
                {
                    pomoRunning = true;
                }
            }

            try
            {
                if (pomoRunning)
                {
                    proc.StartInfo.FileName = fileName;
                    proc.StartInfo.Arguments = Param;
                    proc.Start();
                }
                else
                {
                    proc.StartInfo.FileName = fileName;
                    proc.StartInfo.Arguments = Param;
                    proc.Start();
                    Thread.Sleep(3000);
                    SendKeys.SendWait("{Enter}");
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        int CurrentFile = 0;

        public static void ShuffleInPlace(ArrayList source)
        {
            Random rnd = new Random();
            for (int inx = source.Count - 1; inx > 0; --inx)
            {
                int position = rnd.Next(inx);
                object temp = source[inx];
                source[inx] = source[position];
                source[position] = temp;

                if(_DEBUG_) Console.WriteLine("Do shuffle!!");
            }
        }

        void s_OnTriggerSEQ(string scheduleName)
        {
            try
            {
                if(_DEBUG_) Console.WriteLine("Play type: "+PLAY_TYPE);
                string full = _executeList[CurrentFile].ToString();
                CurrentFile++;
                string[] param = full.Split('#');
                ExecuteProcWithParam(param[0], param[1]);

                #region #Check end.
                if (PLAY_TYPE == "1")//once
                {
                    if (CurrentFile >= _executeList.Count)
                    {
                    }
                }
                if (PLAY_TYPE == "2")//loop
                {
                    if (CurrentFile >= _executeList.Count)
                    {
                        CurrentFile = 0;
                     }
                }
                if (PLAY_TYPE == "3")//once_shuffle
                {
                    if (CurrentFile >= _executeList.Count)
                    {
                        ShuffleInPlace(_executeList);
                        CurrentFile = 0;
                    }
                }
                if (PLAY_TYPE == "4")//loop_shuffle
                {
                    if (CurrentFile >= _executeList.Count)
                    {
                        ShuffleInPlace(_executeList);
                        CurrentFile = 0;
                    }
                }
                #endregion
            }
            catch { }
        }

        private void Main_Load(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
            this.ShowInTaskbar = false;
        }
    }
}
